﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace ThresholdAssistant.WebAPI.Models
{

    /// <summary>
    /// 拓展
    /// </summary>
    public static class CommonExtension
    {
        #region 计算经纬度
        private const double EARTH_RADIUS = 6378137;
        #endregion

        /// <summary>
        /// 去重拓展
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="comparer"></param>
        /// <returns></returns>
        public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source, Func<T, T, bool> comparer)
            where T : class
            => source.Distinct(new DynamicEqualityComparer<T>(comparer));

        /// <summary>
        /// 去重拓展
        /// </summary>
        /// <typeparam name="T"></typeparam>
        private sealed class DynamicEqualityComparer<T> : IEqualityComparer<T> where T : class
        {
            private readonly Func<T, T, bool> _func;

            public DynamicEqualityComparer(Func<T, T, bool> func)
            {
                _func = func;
            }
            public bool Equals(T x, T y) => _func(x, y);
            public int GetHashCode(T obj) => 0;
        }

        /// <summary>
        /// 计算两点位置的距离，返回两点的距离，单位 米
        /// 该公式为GOOGLE提供，误差小于0.2米
        /// </summary>
        /// <param name="lat1">第一点纬度</param>
        /// <param name="lng1">第一点经度</param>
        /// <param name="lat2">第二点纬度</param>
        /// <param name="lng2">第二点经度</param>
        /// <returns></returns>
        public static double GetDistance(double lat1, double lng1, double lat2, double lng2)
        {
            double radLat1 = Rad(lat1);
            double radLng1 = Rad(lng1);
            double radLat2 = Rad(lat2);
            double radLng2 = Rad(lng2);
            double a = radLat1 - radLat2;
            double b = radLng1 - radLng2;
            double result = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2))) * EARTH_RADIUS;
            return result;

        }
        /// <summary>
        /// 经纬度转化成弧度
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        private static double Rad(double d)
        {
            return (double)d * Math.PI / 180d;
        }

        /// <summary>
        /// 生成随机密码
        /// </summary>
        /// <returns></returns>
        public static string GeneratePassword()
        {
            Random random = new Random();
            const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
            const string nums = "0123456789";
            var password = new char[8];
            // Ensure at least one letter and one number
            password[0] = chars[random.Next(chars.Length)];
            password[1] = nums[random.Next(nums.Length)];
            for (int i = 2; i < 8; i++)
            {
                // For the remaining characters, choose randomly between a letter or a number
                if (random.Next(2) == 0)
                {
                    password[i] = chars[random.Next(chars.Length)];
                }
                else
                {
                    password[i] = nums[random.Next(nums.Length)];
                }

            }
            return new string(password);
        }
    }
}